﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel;
using System.Collections.ObjectModel;
using System.ServiceModel.Channels;
using log4net;

namespace Windvoice.Framework.Service
{

    public class ServiceExceptionHandlerAttribute : Attribute, IServiceBehavior, IErrorHandler
    {
        #region IServiceBehavior Member
        /// <summary>
        /// Insert custom error handler to the service.
        /// </summary>
        /// <param name="description">The service description.</param>
        /// <param name="host">The host that is currently being built.</param>
        public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase host)
        {
            foreach (ChannelDispatcher dispatcher in host.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(this);
            }
        }

        /// <summary>
        /// This method is not implemented.
        /// </summary>
        /// <param name="description"></param>
        /// <param name="host"></param>
        /// <param name="endpoints"></param>
        /// <param name="bindingParameters"></param>
        public void AddBindingParameters(ServiceDescription description, ServiceHostBase host, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
        }

        /// <summary>
        /// This method is not implemented.
        /// </summary>
        /// <param name="description"></param>
        /// <param name="host"></param>
        public void Validate(ServiceDescription description, ServiceHostBase host)
        {
        }
        #endregion

        #region IErrorHandler Member

        private static ILog ErrorLogger
        {
            get { return LogManager.GetLogger("errorlogger"); }
        }

        /// <summary>
        /// Logs the exception asyn.
        /// </summary>
        /// <param name="error">The exception which is thrown by the service.</param>
        /// <returns>Whether invokes the other error handlers.</returns>
        public bool HandleError(Exception error)
        {
            ErrorLogger.Error(error);

            return false;
        }

        /// <summary>
        /// Provide custom fault to the client.
        /// </summary>
        /// <param name="error">The exception which is thrown by the service.</param>
        /// <param name="version">The SOAP version of the message.</param>
        /// <param name="fault">The <see cref="System.ServiceModel.Channels.Message"/> object that is returned to the client.</param>
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            FaultException<string> faultException = new FaultException<string>(error.StackTrace, error.Message);
            MessageFault messageFault = faultException.CreateMessageFault();
            fault = Message.CreateMessage(version, messageFault, faultException.Action);
        }
        #endregion
    }
}
